/* low level draw functions. Partially copy-pasted from plplot examples. */

#include "stdio.h"
#include "caml/intext.h"
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "wrappers.h"
#include "ml_gobject.h"
#include "ml_gtk.h"
#include "ml_gdk.h"

/* Set to 0 to draw direct to an X Window, 1 to draw via a pixmap */
#define TO_PIXMAP    1

void setup_plot_drawable( GtkWidget *plotwindow, GdkPixmap *plotwindow_pixmap);

value make_pixmap(value area)
{
  GtkWidget *widget=GtkWidget_val(area);
  GdkPixmap *p = gdk_pixmap_new( widget->window,
	  widget->allocation.width, widget->allocation.height, -1 );
  return Val_GdkPixmap(p);
}

CAMLprim value ev_plotwindow_configure(value area, value pixmap)
{
  GtkWidget *widget=GtkWidget_val(area);
#if TO_PIXMAP != 1
  GTK_WIDGET_UNSET_FLAGS( a, GTK_DOUBLE_BUFFERED );
#endif
  GdkPixmap *plotwindow_pixmap;
#if TO_PIXMAP == 1
  plotwindow_pixmap = GdkPixmap_val(pixmap);
  gdk_pixmap_unref( plotwindow_pixmap );
  plotwindow_pixmap = gdk_pixmap_new( widget->window,
	          widget->allocation.width, widget->allocation.height, -1 );
  printf("allocating new pixmap for window %x (%d,%d) => %x\n",
	  widget->window,widget->allocation.width, widget->allocation.height,
	  plotwindow_pixmap);
#endif
  setup_plot_drawable(widget,plotwindow_pixmap);
  return Val_GdkPixmap(plotwindow_pixmap);
}

int draw_expose(GtkWidget *widget,GdkPixmap *plotwindow_pixmap,GdkEventExpose *ev)
{
#if TO_PIXMAP == 1
  if (ev==NULL) {
//      printf("all expose\n");
      gdk_draw_pixmap( widget->window,
	  widget->style->fg_gc[GTK_WIDGET_STATE( widget )],
	  plotwindow_pixmap, 0, 0, 0, 0, -1, -1 );
  } else {
//      printf("partial expose\n");
      gdk_draw_pixmap( widget->window,
	  widget->style->fg_gc[GTK_WIDGET_STATE( widget )],
	  plotwindow_pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y,
	  ev->area.width, ev->area.height );
  }
#else
  GdkPixmap *plotwindow_pixmap;
  setup_plot_drawable(widget,plotwindow_pixmap);
#endif
  //need not propogate event:
  return TRUE;
}

CAMLprim value ev_plotwindow_expose(value area, value pixmap, value event)
{
  GtkWidget *widget=GtkWidget_val(area);
  GdkPixmap *plotwindow_pixmap = GdkPixmap_val(pixmap);
  GdkEventExpose *ev = GdkEvent_val(event);
  return Val_int(draw_expose(widget,plotwindow_pixmap,ev));
}
CAMLprim value ev_plotwindow_expose_all(value area, value pixmap)
{
  GtkWidget *widget=GtkWidget_val(area);
  GdkPixmap *plotwindow_pixmap = GdkPixmap_val(pixmap);
  return Val_int(draw_expose(widget,plotwindow_pixmap,NULL));
}

#include <plplot.h>

void setup_plot_drawable( GtkWidget *plotwindow, GdkPixmap *plotwindow_pixmap)
{
  struct
  {
    Display  *display;
    Drawable drawable;
  } xinfo;
#if TO_PIXMAP == 1
  xinfo.display  = GDK_PIXMAP_XDISPLAY( plotwindow_pixmap );
  xinfo.drawable = GDK_PIXMAP_XID( plotwindow_pixmap );
#else
  xinfo.display  = GDK_WINDOW_XDISPLAY( plotwindow->window );
  xinfo.drawable = GDK_WINDOW_XID( plotwindow->window );
#endif
  pl_cmd( PLESC_DEVINIT, &xinfo );
}

